using System;
using System.Data;
using System.Web.Mail;
using System.Data.SqlClient;
using System.Collections;


namespace SpringWaterDataAccess
{
	/// <summary>
	/// user object
	/// </summary>
	public class UserObject
	{
		public enum Role
		{
			Reader,
			Writer,
			Publisher,
			Administrator
		}

		string		email;
		string		nickName = "";
		string		roleName = "";
		bool		status =false;
		int			rate = 0;
		DateTime	registerDate;
		DateTime	lastLoginDate;
		DateTime	lastServiceDate;
		string		description;

		#region Constructor Done
		public UserObject(string Email)
		{
			email = Email;
		}
		public UserObject(string Email, string NickName)
		{
			email = Email;
			nickName = NickName;
		}

		public UserObject(string Email, DataRow dr)
		{
			this.email = Email;
			this.UpdateMembers(dr);
		}

		#endregion

		#region Properties Done
		public string Email
		{
			get {return email;}
		}

		public string NickName
		{
			get { return nickName;}
			set { nickName = value;}
		}
		public string RoleName
		{
			get { return roleName;}
			set { roleName = value;}
		}

		public bool Status
		{
			get { return status;}
			set { status = value;}
		}

		public int Rate
		{
			get { return rate;}
			set { rate = value;}
		}


		public DateTime LastLoginDate
		{
			get { return lastLoginDate;}
			set {lastLoginDate = value;}
		}
		public DateTime LastServiceDate
		{
			get { return lastServiceDate;}
			set {lastServiceDate = value;}
		}
		public DateTime RegisterDate
		{
			get { return registerDate;}
			set {registerDate = value;}
		}
		public string Description
		{
			get { return description;}
			set {description = value;}
		}
		public BookShelf MyBookShelf
		{
			get{ return new BookShelf(this);}
		}
		#endregion

		#region StaticMethodsToRetrieveWords in Progress
		/// <summary>
		// return all the published words from SQL Database 
		// caller needs to cast it to Word object
		/// </summary>
		public static DataSet GetPublishedWords()
		{
			SQLAccess sql = new SQLAccess();
			DataSet ds = sql.getWordsByStatus("Approved"); 

			return ds;
		}

		public static DataSet GetPendingWords()
		{
			SQLAccess sql = new SQLAccess();
			DataSet ds = sql.getWordsByStatus("Pending"); 

			return ds;
		}

		public static void ChangeWordStatus(int wordID, 
			int userID, string newStatus) 
		{
			SQLAccess sql = new SQLAccess();
			sql.ChangeWordStatus(wordID,userID,newStatus);
		}

		/// <summary>
		//	return the first N published words from one Category
		//	all category information will be hard-coded
		//	note: there may be less than N words
		/// </summary>
		public static DataSet GetPublishedWords(int recentNWords, Word.Category category)
		{
			SQLAccess sql = new SQLAccess();
			DataSet ds = sql.getWordsByStatus("Approved"); 

			return ds;
		}
		
		/// <summary>
		// return the first N published words from all categories
		// all category information will be hard-coded
		/// </summary>
		public static DataSet GetPublishedWords(int recentNWords)
		{
			// algorithm:	retrieve published words count from each category
			//				loop through each category to retrieve one at a time
			//				until we reach recentNWords or none
			return GetPublishedWords();
		}

		public static DataSet getWordByID(string wordID)
		{
			SQLAccess sql = new SQLAccess();
			DataSet ds = sql.getWordByID(int.Parse(wordID)); 
			return ds;
		}

		public static string getPartner(int partnerID)
		{
			SQLAccess sql = new SQLAccess();
			DataSet ds = sql.getPartner(partnerID); 
			
			return ds.Tables[0].Rows[0]["PartnerCode"].ToString();
	    }

		public static DataRow getPartnerRow(int partnerID)
		{
			SQLAccess sql = new SQLAccess();
			DataSet ds = sql.getPartner(partnerID); 
			
			return ds.Tables[0].Rows[0];
		}

		public static DataSet GetWordsOnMyBookshelf(string email) 
		{
			SQLAccess sql = new SQLAccess();
			return  sql.RetrieveAllWords(email); 
		}

		/// <summary>
		// return one bible verse. The logic will be wrapper into SP
		/// </summary>
		public static string GetOneBibileVerse()
		{
			Random random = new Random();
			int which = random.Next(10);
			return string.Format("Next Verse ID will be {0}", which);
		}

		public static void AddWord(string title, int categoryID,
			int partnerID, string originAuthor, string description,
			string url, int userID,string recommendBy,DateTime pubDate) 
		{
			SQLAccess sql = new SQLAccess();
		    sql.AddWord(title, categoryID,
				partnerID,originAuthor,description,
				url, userID,recommendBy, pubDate);
		
		}


        public static void IncreaseNumberClicks(string wordID)
        {
            SQLAccess sql = new SQLAccess();
            if (wordID != null)
            {
                sql.IncreaseNumberClicks(int.Parse(wordID));
            }
        }

		public static void AddWordToShelf(string email, int wordID) 
		{
			SQLAccess sql = new SQLAccess();
			sql.AddOneWord(email, wordID);
		}

		public static void RemoveWordFromShelf(int wordID,string email) 
		{
			SQLAccess sql = new SQLAccess();
			sql.DeleteWord(email, wordID);
		}

		#endregion

		#region StaticMethodsForUserLoginRegister Done
		/// <summary>
		// login on user: null -- fail, UserObject -- succeed
		/// </summary>
		public static UserObject LoginOn(string email, string password)
		{
			SQLAccess sql = new SQLAccess();
			DataSet userData = sql.LoginUser(email,password);
			if (userData.Tables.Count == 0 || userData.Tables[0].Rows.Count==0)
				throw new Exception("Login Failed, please check user name and password");
			
			// now construct user object
			//UserObject user = new UserObject(email, 
			return new UserObject(email, userData.Tables[0].Rows[0]);
					
		}

		/// <summary>
		/// get user information with "email" input
		// RetrieveUserInfo: null -- failed UserObject -- succeed
		/// </summary>
		public static UserObject RetrieveUserInfo(string email)
		{
			SQLAccess sql = new SQLAccess();
			DataSet userData = sql.GetUser(email);
			if (userData.Tables.Count == 0 || userData.Tables[0].Rows.Count==0)
			{
				//throw new Exception("Retrieve User Info Failed, please check user name");
				return null;
			}

			// now construct user object
			//UserObject user = new UserObject(email, 
			return new UserObject(email, userData.Tables[0].Rows[0]);
		}

		public static DataSet GetUser(string email) 
		{
			SQLAccess sql = new SQLAccess();
			return sql.GetUser(email);
		}

		public static DataSet GetUserByID(int userID) 
		{
			SQLAccess sql = new SQLAccess();
			return sql.GetUserByID(userID);
		}

		/// <summary>
		/// get user information and save it into database with user input
		// register a new user: null -- failed UserObject -- succeed
		/// </summary>
		public static UserObject Register(string email, 
			  string password, string nickName, string recommendBy, string faith, string ipAddress)
		{
			SQLAccess sql = new SQLAccess();
			sql.AddUser(email,password,nickName,recommendBy,faith,ipAddress);
			
			return new UserObject(email,nickName);
		}

		public static string getUserName(object UserID) 
		{
			if (UserID == Convert.DBNull || 
				Convert.ToString(UserID) == "") 
			{
				return "";
			}
			SQLAccess sql = new SQLAccess();
			DataSet dsUser = sql.GetUserByID(Convert.ToUInt16(UserID));
			return dsUser.Tables[0].Rows[0]["NickName"].ToString();
		}

		/// <summary>
		// remove the user from the database
		/// </summary>
		public static bool DeleteUser(string email)
		{
			SQLAccess sql = new SQLAccess();
			sql.DeleteUser(email);
			return true;
		}

		/// <summary>
		//  send user's password to the following email address, based upon the email
		//	this will be carried out in SQL or Web Server depending upon availablity
		/// </summary>
		public static string GetPassword(string email)
		{
			 
			SQLAccess sql = new SQLAccess();
			DataSet userData = sql.GetUserPassword(email);
			if (userData.Tables.Count == 0 || userData.Tables[0].Rows.Count==0)
				return "";
			
			return userData.Tables[0].Rows[0][0].ToString();
		}
		#endregion

		#region PrivateMethods
		private void UpdateMembers(DataRow dr)
		{
			this.nickName = dr["NickName"] is DBNull ?"": dr["NickName"].ToString();
			this.roleName = dr["RoleName"].ToString();
			this.status = dr["Status"] is DBNull ?false: null == dr["Status"].ToString()?false:true;
			this.rate = dr["Rate"] is DBNull ? 0 : int.Parse(dr["Rate"].ToString());
			this.registerDate = (DateTime)dr["RegisterDate"];
			this.lastLoginDate = (DateTime)dr["LastLoginDate"];
			if (!(dr["LastServiceDate"] is DBNull)) this.lastServiceDate= (DateTime)dr["LastServiceDate"];
			this.description = dr["Description"] is DBNull ?"": dr["Description"].ToString();
		}
		#endregion
	}
}
